<?php declare(strict_types=1);

use App\Models\Mysql\XnMerchant;
use Illuminate\Support\Arr;
use Illuminate\Http\JsonResponse;
use App\Models\Admin\Supplier as SupplierModel;
use Illuminate\Support\Facades\Config;

/**
 * 是否是手机号
 *
 * @param string $phone
 * @return false
 */
function isPhone(string $phone): bool
{
    return (bool) preg_match('/^1[0-9]{10}$/', $phone);
}

function yunfacurl_https($url, $data = array(), $contentType = '', $header = array(), $timeout = 30, $debug = false) {
    $ch = curl_init();
    $data = $contentType == 'json' ? urldecode(json_encode($data)) : http_build_query($data);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    if(!empty($data)){
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    }


    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    $response = curl_exec($ch);

    if ($error = curl_error($ch)) {
        die($error);
    }

    // 打印错误信息
    if ($debug) {

        echo '=====info====='."\r\n";
        print_r(curl_getinfo($ch));

        echo '=====error====='."\r\n";
        print_r(curl_error($ch));

        echo '=====$response====='."\r\n";
        print_r($response);

    }
    curl_close($ch);
    return $response;
}
/**
 * @param Throwable $e
 * @return array
 */
function error2array(Throwable $e): array
{
    return [
        'message' => $e->getMessage(),
        'exception' => get_class($e),
        'file' => $e->getFile(),
        'line' => $e->getLine(),
        'trace' => collect($e->getTrace())->slice(0, 10)
            ->map(fn($trace) =>
                sprintf("%s[%s] %s %s %s", $trace['file'], $trace['line'] ?? '未知', $trace['class'] ?? '', $trace['type'] ?? '', $trace['function'] ?? '')
            )
            ->all(),
    ];
}

/**
 * @param array $array
 * @return false|string
 */
function array2json(array $array): bool|string
{
    return json_encode($array, 320);
}

/**
 * @param mixed $json
 * @return array
 */
function json2array(mixed $json): array
{
    if (!$json) {
        return [];
    }
    return json_decode($json, true) ?? [];
}

/**
 * @param mixed $xml
 * @return array
 */
function xml2array(mixed $xml): array
{
    try {
        if (!$xml) {
            return [];
        }
        $data = simplexml_load_string($xml);
        return json_decode(json_encode($data), true) ?? [];
    } catch (Throwable $e) {
        return [];
    }
}

/**
 * 加密字符串
 * @param string $data 字符串
 * @param string $key 加密key
 * @param string $cipher_algo 加密方式
 * @param int $options
 * @param string $iv
 * @param bool $base64 是否base64
 * @return string|false
 */
function encryptWithOpenssl(
    string $data,
    string $key,
    string $cipher_algo = 'AES-256-ECB',
    int    $options = OPENSSL_RAW_DATA,
    string $iv = '',
    bool   $base64 = true
): bool|string
{
    $str = openssl_encrypt($data, $cipher_algo, $key, $options, $iv);
    return $base64 ? base64_encode($str) : $str;
}

/**
 * 解密
 *
 * @param string $data
 * @param string $key
 * @param string $cipher_algo
 * @param int $options
 * @param string $iv
 * @param bool $base64
 * @return false|string
 */
function decryptWithOpenssl(
    string $data,
    string $key,
    string $cipher_algo = 'AES-256-ECB',
    int    $options = OPENSSL_RAW_DATA,
    string $iv = '',
    bool   $base64 = true
): bool|string
{
    return openssl_decrypt($base64 ? base64_decode($data) : $data, $cipher_algo, $key, $options, $iv);
}

/**
 * 毫秒时间戳
 *
 * @return int
 */
function millisecondTimestamp(): int
{
    list($time, $sec) = explode(' ', microtime());
    return intval(sprintf('%.0f', (floatval($time) + floatval($sec)) * 1000));
}


/**
 * @param string $message
 * @param int $code
 * @param mixed $info
 * @return JsonResponse
 */
function fails(string $message, int $code = 2, mixed $info = null): JsonResponse
{
    $headers = ['Content-Type' => 'application/json;charset=UTF-8', 'charset' => 'utf-8','access-control-allow-origin'=>'*'];
    $arr = [
        'code' => $code,
        'message' => $message,
        'data' => $info
    ];
    return response()->json($arr, 200, $headers, JSON_UNESCAPED_UNICODE);
}

/**
 * @param mixed $info
 * @param int $code
 * @param string $message
 * @return JsonResponse
 */
function successly(mixed $info = [], int $code = 200, string $message = '成功'): JsonResponse
{
    $headers = ['Content-Type' => 'application/json;charset=UTF-8', 'charset' => 'utf-8','access-control-allow-origin'=>'*'];
    $arr = [
        'code' => $code,
        'message' => $message,
        'data' => $info
    ];
    return response()->json($arr, 200, $headers, JSON_UNESCAPED_UNICODE);
}


/**
 * 使用curl方式实现get或post请求
 * @param string $url 请求的url地址
 * @param mixed $data 发送的post数据 如果为空则为get方式请求
 * return 请求后获取到的数据
 */
function curlRequest($url, $data = '')
{
    $ch = curl_init();
    $params[CURLOPT_URL] = $url;    //请求url地址
    $params[CURLOPT_HEADER] = false; //是否返回响应头信息
    $params[CURLOPT_RETURNTRANSFER] = true; //是否将结果返回
    $params[CURLOPT_FOLLOWLOCATION] = true; //是否重定向
    $params[CURLOPT_TIMEOUT] = 30; //超时时间
    if (!empty($data)) {
        $params[CURLOPT_POST] = true;
        $params[CURLOPT_POSTFIELDS] = $data;
    }
    $params[CURLOPT_SSL_VERIFYPEER] = false;//请求https时设置,还有其他解决方案
    $params[CURLOPT_SSL_VERIFYHOST] = false;//请求https时,其他方案查看其他博文
    curl_setopt_array($ch, $params); //传入curl参数
    $content = curl_exec($ch); //执行
    curl_close($ch); //关闭连接
    return $content;
}

function curlcheng_post($url, $data)

{
    $curl = curl_init();

    curl_setopt($curl, CURLOPT_URL, $url);

    curl_setopt($curl, CURLOPT_HEADER, 0);//不抓取头部信息。只返回数据

    curl_setopt($curl, CURLOPT_TIMEOUT, 10);//超时设置

    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);//1表示不返回bool值

    curl_setopt($curl, CURLOPT_POST, 1);

    curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));//重点

    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));

    $response = curl_exec($curl);

    if (curl_errno($curl)) {
        return curl_error($curl);

    }

    curl_close($curl);

    return $response;
}


/**
 * @param array $array
 * @return bool|string
 */
function asc_sort(array $array): bool|string
{
    if (empty($array)) {
        return false;
    }
    ksort($array);
    $str = '';
    foreach ($array as $k => $val) {
        $str .= $k . '=' . $val . '&';
    }
    return rtrim($str, '&');
}

/**
 * 获取当前域名
 * @return string
 */
function getHttpType(): string
{
    $http = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://';
    return $http . $_SERVER['HTTP_HOST'];
}

/**
 * @param string $startDate
 * @param string $endDate
 * @return array
 */
function getDateFromRange(string $startDate, string $endDate): array
{

    $startTimestamp = strtotime($startDate);
    $endTimestamp = strtotime($endDate);
    // 计算日期段内有多少天
    $days = ($endTimestamp - $startTimestamp) / 86400 + 1;
    // 保存每天日期
    $date = array();
    for ($i = 0; $i < $days; $i++) {
        $date[] = date('Y-m-d', $startTimestamp + (86400 * $i));
    }
    return $date;
}
function getMonthsBetweenDates($startDate, $endDate) {
    $start = new DateTime($startDate);
    $end = new DateTime($endDate);
    $end->add(new DateInterval('P1M')); // 将结束日期向前推进一个月，确保包含最后一个月
    $interval = new DateInterval('P1M');
    $period = new DatePeriod($start, $interval, $end);

    $months = [];
    foreach ($period as $date) {
        $months[] = $date->format('Y-m');
    }

    return $months;
}

/**
 * @param array $array
 * @param string $keys
 * @param string $sort
 * @return array
 */
function arraySort(array $array, string $keys, string $sort = 'desc'): array
{
    $newArr = $valArr = array();
    foreach ($array as $key => $value) {
        $valArr[$key] = $value[$keys];
    }
    ($sort == 'asc') ? asort($valArr) : arsort($valArr);
    foreach ($valArr as $key => $value) {
        $newArr[$key] = $array[$key];
    }
    return array_values($newArr);
}

/**
 * 检测db是否注册config
 *
 * @param string $dbKey
 * @return false|string
 */
function checkDbConnectIsRegister(string $dbKey): bool|string
{
    return empty(Config::get('database.connections.' . $dbKey, []));
}

/**
 * db注册config
 *
 * @param SupplierModel|int $supplier 供应商
 * @return mixed
 */
function dbRegister(SupplierModel|int $supplier): mixed
{
    /** @var SupplierModel|null $supplier * */
    if (! $supplier instanceof SupplierModel) {
        $supplier = SupplierModel::query()->find($supplier);
    }
    if (!$supplier) {
        return false;
    }
    return $supplier->registerDbConnect();
}

/**
 * db-connect-key
 *
 * @param SupplierModel|int $sid 供应商
 * @return string
 */
function dbConnectKey(SupplierModel|int $sid): string
{
    return'supplier@'. ($sid instanceof SupplierModel ? $sid->id : $sid);
}

/**
 * 接口加密方式sign
 */
function isSign($info){
    $secret_key = XnMerchant:: where('Merchant_number',$info['merchant_number']) -> value('secret_key');
    $old_sign = $info['sign'];
    $info = array_filter($info, function ($item) {
        return !empty($item);
    });
    unset($info['sign']);
    ksort($info);
    $new_sign = md5(json_encode($info).$secret_key);
    if($old_sign != $new_sign){
        return false;
    }
    return true;
}

/**
 * 将数值金额转换为中文大写金额
 * @param $amount float 金额(支持到分)
 * @param $type   int   补整类型,0:到角补整;1:到元补整
 * @return mixed 中文大写金额
 */
function Number_conversion_to_uppercase($amount, $type = 1) {
    // 判断输出的金额是否为数字或数字字符串
    if(!is_numeric($amount)){
        return "要转换的金额只能为数字!";
    }

    // 金额为0,则直接输出"零元整"
    if($amount == 0) {
        return "人民币零元整";
    }

    // 金额不能为负数
    if($amount < 0) {
        return "要转换的金额不能为负数!";
    }

    // 金额不能超过万亿,即12位
    if(strlen($amount) > 12) {
        return "要转换的金额不能为万亿及更高金额!";
    }

    // 预定义中文转换的数组
    $digital = array('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖');
    // 预定义单位转换的数组
    $position = array('仟', '佰', '拾', '亿', '仟', '佰', '拾', '万', '仟', '佰', '拾', '元');

    // 将金额的数值字符串拆分成数组
    $amountArr = explode('.', $amount);

    // 将整数位的数值字符串拆分成数组
    $integerArr = str_split($amountArr[0], 1);

    // 将整数部分替换成大写汉字

    $integerArrLength = count($integerArr);     // 整数位数组的长度
    $positionLength = count($position);         // 单位数组的长度
    for($i = 0; $i < $integerArrLength; $i++) {
        // 如果数值不为0,则正常转换
        if($integerArr[$i] != 0){
            $result =   $digital[$integerArr[$i]] . $position[$positionLength - $integerArrLength + $i];
        }else{
            // 如果数值为0, 且单位是亿,万,元这三个的时候,则直接显示单位
            if(($positionLength - $integerArrLength + $i + 1)%4 == 0){
                $result = $position[$positionLength - $integerArrLength + $i];
            }
        }
    }

    // 如果小数位也要转换
    if($type == 0) {
        // 将小数位的数值字符串拆分成数组
        $decimalArr = str_split($amountArr[1], 1);
        // 将角替换成大写汉字. 如果为0,则不替换
        if($decimalArr[0] != 0){
            $result = $result . $digital[$decimalArr[0]] . '角';
        }
        // 将分替换成大写汉字. 如果为0,则不替换
        if($decimalArr[1] != 0){
            $result = $result . $digital[$decimalArr[1]] . '分';
        }
    }else{
        $result = $result . '整';
    }
    return $result;
}
//福禄请求http
function curl_post($url,$data){
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);//// 跳过证书检查
    curl_setopt($ch, CURLOPT_TIMEOUT, '60');
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'Content-Length: ' . strlen($data)
    ));
    $result = curl_exec($ch);
    if (curl_errno($ch)) {
        print curl_error($ch);
    }
    curl_close($ch);
    return $result;
}

function baimiaorequest($url,$post,$headers){
    //初始化
    $curl = curl_init();
    //设置抓取的url
    curl_setopt($curl, CURLOPT_URL, $url);
    //设置头文件的信息作为数据流输出
    curl_setopt($curl, CURLOPT_HEADER, 0);
    //设置请求头
    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    //设置获取的信息以文件流的形式返回，而不是直接输出。
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    //设置post方式提交
    curl_setopt($curl, CURLOPT_POST, 1);
    //设置头文件的信息作为数据流输出
    //curl_setopt($curl, CURLOPT_HEADER, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
    //执行命令
    $data = curl_exec($curl);
    //关闭URL请求
    curl_close($curl);
    //显示获得的数据
    return $data;
}
/** 获取毫秒级别
 * @return float
 */
function getMsecTime()
{
    list($msec, $sec) = explode(' ', microtime());
    $msectime =  (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
    return $msectime;
}
//Xml转数组
function XmlToArr($xml)
{
    if($xml == '') return '';
    libxml_disable_entity_loader(true);
    $arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    return $arr;
}

// 硕软接口调用方法
function srcurl($url, $data)
{
    $url = trim($url);
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept-Encoding: gzip, deflate'));
    curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    $curl_result = curl_exec($ch);
    $curl_result = mb_convert_encoding($curl_result, 'utf-8', 'GBK,UTF-8,ASCII');
    $result_json = json_decode($curl_result, true);
    return $result_json;
}
//子轩post请求接口
function zixuan_post($url, $data)
{
    $curl = curl_init();

    curl_setopt($curl, CURLOPT_URL, $url);

    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);

    curl_setopt($curl, CURLOPT_HEADER, 0);//不抓取头部信息。只返回数据

    curl_setopt($curl, CURLOPT_TIMEOUT,1000);//超时设置

    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);//1表示不返回bool值

    curl_setopt($curl, CURLOPT_POST, 1);

    curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));//重点

    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));

    $response = curl_exec($curl);

    if (curl_errno($curl)) {
        return curl_error($curl);

    }

    curl_close($curl);

    return $response;
}
